#include "keybindings.h"
#include <allegro5/allegro5.h>
using namespace std;

const int KeyBindings::NO_KEY = -1;

KeyBindings::KeyBindings() {
     setDefaults();
}

KeyBindings::~KeyBindings() {
}

void KeyBindings::init(ALLEGRO_CONFIG *pConfig) {

     // read in key bindings
     void *pIter;
     const char *key=NULL, *val=NULL;
     string keystr, valstr;
     int k = 0;
     const char * const section = "keys";
     int action = KeyBindings::NoAction;
     for (key = al_get_first_config_entry(pConfig, section, &pIter); 
	  key;
	  key = al_get_next_config_entry(&pIter)) {

	  val = al_get_config_value(pConfig, section, key);
	  if (val) {
	       keystr = key;
	       valstr = val;
	       action = strToAction(valstr);
	       k = strToKey(keystr);
	       m_bindings[k] = action;
	  }
     }
}

void KeyBindings::setDefaults() {
     m_bindings[KeyBindings::NO_KEY] = KeyBindings::NoAction;
     m_bindings[ALLEGRO_KEY_Z] = KeyBindings::NoteC0;
     m_bindings[ALLEGRO_KEY_S] = KeyBindings::NoteCS0;
     m_bindings[ALLEGRO_KEY_X] = KeyBindings::NoteD0;
     m_bindings[ALLEGRO_KEY_D] = KeyBindings::NoteDS0;
     m_bindings[ALLEGRO_KEY_C] = KeyBindings::NoteE0;
     m_bindings[ALLEGRO_KEY_V] = KeyBindings::NoteF0;
     m_bindings[ALLEGRO_KEY_G] = KeyBindings::NoteFS0;
     m_bindings[ALLEGRO_KEY_B] = KeyBindings::NoteG0;
     m_bindings[ALLEGRO_KEY_H] = KeyBindings::NoteGS0;
     m_bindings[ALLEGRO_KEY_N] = KeyBindings::NoteA0;
     m_bindings[ALLEGRO_KEY_J] = KeyBindings::NoteAS0;
     m_bindings[ALLEGRO_KEY_M] = KeyBindings::NoteB0;
     m_bindings[ALLEGRO_KEY_Q] = KeyBindings::NoteC1;
     m_bindings[ALLEGRO_KEY_2] = KeyBindings::NoteCS1;
     m_bindings[ALLEGRO_KEY_W] = KeyBindings::NoteD1;
     m_bindings[ALLEGRO_KEY_3] = KeyBindings::NoteDS1;
     m_bindings[ALLEGRO_KEY_E] = KeyBindings::NoteE1;
     m_bindings[ALLEGRO_KEY_R] = KeyBindings::NoteF1;
     m_bindings[ALLEGRO_KEY_5] = KeyBindings::NoteFS1;
     m_bindings[ALLEGRO_KEY_T] = KeyBindings::NoteG1;
     m_bindings[ALLEGRO_KEY_6] = KeyBindings::NoteGS1;
     m_bindings[ALLEGRO_KEY_Y] = KeyBindings::NoteA1;
     m_bindings[ALLEGRO_KEY_7] = KeyBindings::NoteAS1;
     m_bindings[ALLEGRO_KEY_U] = KeyBindings::NoteB1;
     m_bindings[ALLEGRO_KEY_DOWN] = KeyBindings::RowUp;
     m_bindings[ALLEGRO_KEY_UP] = KeyBindings::RowDown;
     m_bindings[ALLEGRO_KEY_RIGHT] = KeyBindings::FieldUp;
     m_bindings[ALLEGRO_KEY_LEFT] = KeyBindings::FieldDown;
     m_bindings[ALLEGRO_KEY_LSHIFT] = KeyBindings::EventType;
     m_bindings[ALLEGRO_KEY_DELETE] = KeyBindings::Delete;
     m_bindings[ALLEGRO_KEY_TILDE] = KeyBindings::NoteOff;
     m_bindings[ALLEGRO_KEY_SPACE] = KeyBindings::TogglePlay;
}

int KeyBindings::strToKey(string &keyStr) {
     if (keyStr == "A")
	  return ALLEGRO_KEY_A;
     if (keyStr == "B")
	  return ALLEGRO_KEY_B;
     if (keyStr == "C")
	  return ALLEGRO_KEY_C;
     if (keyStr == "D")
	  return ALLEGRO_KEY_D;
     if (keyStr == "E")
	  return ALLEGRO_KEY_E;
     if (keyStr == "F")
	  return ALLEGRO_KEY_F;
     if (keyStr == "G")
	  return ALLEGRO_KEY_G;
     if (keyStr == "H")
	  return ALLEGRO_KEY_H;
     if (keyStr == "I")
	  return ALLEGRO_KEY_I;
     if (keyStr == "J")
	  return ALLEGRO_KEY_J;
     if (keyStr == "K")
	  return ALLEGRO_KEY_K;
     if (keyStr == "L")
	  return ALLEGRO_KEY_L;
     if (keyStr == "M")
	  return ALLEGRO_KEY_M;
     if (keyStr == "N")
	  return ALLEGRO_KEY_N;
     if (keyStr == "O")
	  return ALLEGRO_KEY_O;
     if (keyStr == "P")
	  return ALLEGRO_KEY_P;
     if (keyStr == "Q")
	  return ALLEGRO_KEY_Q;
     if (keyStr == "R")
	  return ALLEGRO_KEY_R;
     if (keyStr == "S")
	  return ALLEGRO_KEY_S;
     if (keyStr == "T")
	  return ALLEGRO_KEY_T;
     if (keyStr == "U")
	  return ALLEGRO_KEY_U;
     if (keyStr == "V")
	  return ALLEGRO_KEY_V;
     if (keyStr == "W")
	  return ALLEGRO_KEY_W;
     if (keyStr == "X")
	  return ALLEGRO_KEY_X;
     if (keyStr == "Y")
	  return ALLEGRO_KEY_Y;
     if (keyStr == "Z")
	  return ALLEGRO_KEY_Z;
     if (keyStr == "1")
	  return ALLEGRO_KEY_1;
     if (keyStr == "2")
	  return ALLEGRO_KEY_2;
     if (keyStr == "3")
	  return ALLEGRO_KEY_3;
     if (keyStr == "4")
	  return ALLEGRO_KEY_4;
     if (keyStr == "5")
	  return ALLEGRO_KEY_5;
     if (keyStr == "6")
	  return ALLEGRO_KEY_6;
     if (keyStr == "7")
	  return ALLEGRO_KEY_7;
     if (keyStr == "8")
	  return ALLEGRO_KEY_8;
     if (keyStr == "9")
	  return ALLEGRO_KEY_9;
     if (keyStr == "0")
	  return ALLEGRO_KEY_0;
     if (keyStr == "Apostrophe")
	  return ALLEGRO_KEY_QUOTE;
     if (keyStr == "Comma")
	  return ALLEGRO_KEY_COMMA;
     if (keyStr == "Period")
	  return ALLEGRO_KEY_FULLSTOP;
     if (keyStr == "Semicolon")
	  return ALLEGRO_KEY_SEMICOLON;

     return KeyBindings::NO_KEY;
}

int KeyBindings::strToAction(string &actionStr) {
     if (actionStr == "NoteC0")
	  return KeyBindings::NoteC0;
     if (actionStr == "NoteCS0")
	  return KeyBindings::NoteCS0;
     if (actionStr == "NoteD0")
	  return KeyBindings::NoteD0;
     if (actionStr == "NoteDS0")
	  return KeyBindings::NoteDS0;
     if (actionStr == "NoteE0")
	  return KeyBindings::NoteE0;
     if (actionStr == "NoteF0")
	  return KeyBindings::NoteF0;
     if (actionStr == "NoteFS0")
	  return KeyBindings::NoteFS0;
     if (actionStr == "NoteG0")
	  return KeyBindings::NoteG0;
     if (actionStr == "NoteGS0")
	  return KeyBindings::NoteGS0;
     if (actionStr == "NoteA0")
	  return KeyBindings::NoteA0;
     if (actionStr == "NoteAS0")
	  return KeyBindings::NoteAS0;
     if (actionStr == "NoteB0")
	  return KeyBindings::NoteB0;
     if (actionStr == "NoteC1")
	  return KeyBindings::NoteC1;
     if (actionStr == "NoteCS1")
	  return KeyBindings::NoteCS1;
     if (actionStr == "NoteD1")
	  return KeyBindings::NoteD1;
     if (actionStr == "NoteDS1")
	  return KeyBindings::NoteDS1;
     if (actionStr == "NoteE1")
	  return KeyBindings::NoteE1;
     if (actionStr == "NoteF1")
	  return KeyBindings::NoteF1;
     if (actionStr == "NoteFS1")
	  return KeyBindings::NoteFS1;
     if (actionStr == "NoteG1")
	  return KeyBindings::NoteG1;
     if (actionStr == "NoteGS1")
	  return KeyBindings::NoteGS1;
     if (actionStr == "NoteA1")
	  return KeyBindings::NoteA1;
     if (actionStr == "NoteAS1")
	  return KeyBindings::NoteAS1;
     if (actionStr == "NoteB1")
	  return KeyBindings::NoteB1;
     if (actionStr == "RowUp")
	  return KeyBindings::RowUp;
     if (actionStr == "RowDown")
	  return KeyBindings::RowDown;
     if (actionStr == "FieldUp")
	  return KeyBindings::FieldUp;
     if (actionStr == "FieldDown")
	  return KeyBindings::FieldDown;
     if (actionStr == "ColUp")
	  return KeyBindings::ColUp;
     if (actionStr == "ColDown")
	  return KeyBindings::ColDown;
     if (actionStr == "EventType")
	  return KeyBindings::EventType;
     
     return KeyBindings::NoAction;
}

int KeyBindings::keyAction(int key, int modifiers) {
     if (modifiers & ALLEGRO_KEYMOD_CTRL)
	  return KeyBindings::NoAction;
     return m_bindings[key];
}

bool KeyBindings::keyIsHex(int key) {
     switch (key) {
     case ALLEGRO_KEY_0:
     case ALLEGRO_KEY_1:
     case ALLEGRO_KEY_2:
     case ALLEGRO_KEY_3:
     case ALLEGRO_KEY_4:
     case ALLEGRO_KEY_5:
     case ALLEGRO_KEY_6:
     case ALLEGRO_KEY_7:
     case ALLEGRO_KEY_8:
     case ALLEGRO_KEY_9:
     case ALLEGRO_KEY_A:
     case ALLEGRO_KEY_B:
     case ALLEGRO_KEY_C:
     case ALLEGRO_KEY_D:
     case ALLEGRO_KEY_E:
     case ALLEGRO_KEY_F:
	  return true;
     }
     return false;
}

int KeyBindings::hexKeyInt(int key) {
     switch (key) {
     case ALLEGRO_KEY_0:
	  return 0;
     case ALLEGRO_KEY_1:
	  return 1;
     case ALLEGRO_KEY_2:
	  return 2;
     case ALLEGRO_KEY_3:
	  return 3;
     case ALLEGRO_KEY_4:
	  return 4;
     case ALLEGRO_KEY_5:
	  return 5;
     case ALLEGRO_KEY_6:
	  return 6;
     case ALLEGRO_KEY_7:
	  return 7;
     case ALLEGRO_KEY_8:
	  return 8;
     case ALLEGRO_KEY_9:
	  return 9;
     case ALLEGRO_KEY_A:
	  return 10;
     case ALLEGRO_KEY_B:
	  return 11;
     case ALLEGRO_KEY_C:
	  return 12;
     case ALLEGRO_KEY_D:
	  return 13;
     case ALLEGRO_KEY_E:
	  return 14;
     case ALLEGRO_KEY_F:
	  return 15;
     }
     return -1;
}
